import CursorData from "../data/CursorData"
import RaycasterData from "../data/RaycasterData"
import renderOrderEnum from "../enum/renderOrder.enum"
import styleEnum from "../enum/style.enum"
import TextureLoader from "../loader/TextureLoader"
import Vectors from "../three/Vectors"
import RenderLayers, { RenderLayer } from "../utils/RenderLayers"
import se from "../math/69626"
import * as THREE from "three"
import WebGLScene from "../three/WebGLScene"
import { InputSubscription } from "../module/InputIniModule"
import EngineContext from "../EngineContext"
import { Subscription } from "../utils/Subscription"
export default class GridPlaneCursor {
  scene: WebGLScene
  layer: RenderLayer
  supportsMobile: boolean
  style: number
  alignToNormal: boolean
  xzTex: THREE.Texture
  zyTex: THREE.Texture
  bindings: Subscription[]
  onOpacityUpdate: (e: any) => void
  container: THREE.Group
  onPositionUpdate: (e: THREE.Vector3, t: THREE.Vector3) => void
  scale: (e: any) => void
  onRaycasterUpdate: (e: any) => void
  xzMaterial: THREE.MeshBasicMaterial
  zyMaterial: THREE.MeshBasicMaterial
  constructor(e, t = RenderLayers.ALL) {
    this.scene = e
    this.layer = t
    this.supportsMobile = !0
    this.style = styleEnum.GridPlane
    this.alignToNormal = !0
    this.xzTex = TextureLoader("./images/vert_arrows.png")
    this.zyTex = TextureLoader("./images/surface_grid_planar_256.png")
    this.bindings = []
    this.onOpacityUpdate = e => {
      this.container.children.forEach((t: any) => {
        t.isMesh && (t.material.opacity = Math.max(0, e.opacity.value))
      })
    }
    this.onPositionUpdate = (e, t) => {
      this.container.position.copy(e).addScaledVector(t, 0.005)
      this.alignToNormal && se.J2(this.container, e, t)
    }
    this.scale = e => {
      this.container.scale.set(e, e, e)
    }
    this.onRaycasterUpdate = e => {
      e.hit && e.hit.face && this.onPositionUpdate(e.hit.point.clone(), e.hit.face.normal)
    }
    this.container = new THREE.Group()
    const i = new THREE.PlaneGeometry(0.4, 0.4)
    const s = {
      color: 16777215,
      side: THREE.DoubleSide,
      transparent: !0,
      depthTest: !0,
      depthWrite: !1
    }
    this.xzTex.generateMipmaps = !1
    this.xzTex.minFilter = THREE.LinearFilter
    this.xzMaterial = new THREE.MeshBasicMaterial(
      Object.assign(Object.assign({}, s), {
        color: 65280,
        map: this.xzTex
      })
    )
    this.xzMaterial.premultipliedAlpha = !1
    const n = new THREE.Mesh(i, this.xzMaterial)
    n.rotateOnAxis(Vectors.LEFT, Math.PI / 2)
    this.zyTex.generateMipmaps = !1
    this.zyTex.minFilter = THREE.NearestFilter
    this.zyMaterial = new THREE.MeshBasicMaterial(Object.assign(Object.assign({}, s), { map: this.zyTex }))
    this.zyMaterial.premultipliedAlpha = !1
    const r = new THREE.Mesh(i, this.zyMaterial)
    this.container.add(n, r)
    this.container.children.forEach(e => {
      e.renderOrder = renderOrderEnum.reticule
      e.layers.mask = this.layer.mask
    })
  }
  init() {}
  render() {}
  dispose() {
    this.container.children.forEach((e: any) => {
      if (e.isMesh) {
        e.geometry.dispose()
        const t = e.material
        t.dispose(), t.map && t.map.dispose()
      }
    })
  }
  async activate(e: EngineContext) {
    const t = await e.market.waitForData(CursorData)
    const i = await e.market.waitForData(RaycasterData)
    this.bindings.push(t.onChanged(this.onOpacityUpdate), i.onChanged(this.onRaycasterUpdate))
    this.scene.add(this.container)
  }
  deactivate() {
    for (const e of this.bindings) e.cancel()
    this.bindings.length = 0
    this.scene.remove(this.container)
  }
  setVisible(e: boolean) {
    this.container.visible = e
  }
}
